#ifndef __DEVICE_H__
#define __DEVICE_H__
#include "shyper_service.h"

#define NAME_MAX_LEN (32)
#define PLATFORM_CPU_NUM_MAX (8)
#define VM_REGION_MAX (8)
#define IRQ_MAX_NUM (0x40)
#define NIC_STATE_MAX_NUM (0x10)
#define BLK_STATE_MAX_NUM (0x10)

typedef volatile u32 spinlock; // linux has struct spinlock_t
typedef u32 bitmap_t;

enum dev_mode {
    PASSTHROUGH_MODE,
    EMULATION_MODE,
};

struct dev_info {
    u32 id;
    char name[NAME_MAX_LEN];
    enum dev_mode mode;
    u64 ipa;
    u64 pa;
    u64 length;
    u32 irq_num;
    u8 irqs[IRQ_MAX_NUM];
};

enum cpu_state {
    CPU_STATE_INV,
    CPU_STATE_PENDING,
    CPU_STATE_ACTIVE,
};

struct dev_cpu_state {
    u32 num;
    u8 name[PLATFORM_CPU_NUM_MAX];
    u8 state[PLATFORM_CPU_NUM_MAX];
};

struct mem_region {
    u64 idx;
    u64 base;
    u64 size;
    u64 free;
    u64 last;
};

// linux has a struct vm_region
struct vmm_region {
    struct mem_region region[VM_REGION_MAX];
    u64 num;
};

struct heap_region {
    struct mem_region region;
    spinlock lock;
    bitmap_t *map;
};

struct dev_mem_state {
    u64 phys_size;
    struct vmm_region vm_mem_state;
    struct heap_region heap_state;
};

struct blk_stat {
    u64 read_req;
    u64 write_req;
    u64 read_byte;
    u64 write_byte;
};

struct dev_blk_state {
    u64 start_sector;
    u64 sector_num;
    struct blk_stat stat;
};
struct dev_storage_state {
    u32 totol_sector_num;
    u32 per_sector_size;
    u32 blk_num;
    struct dev_blk_state state[BLK_STATE_MAX_NUM];
};

struct nic_stat {
    u64 send_req;
    u64 receive_req;
    u64 send_bytes;
    u64 receive_byte;
    u64 discard;
};

struct dev_nic_state {
    u8 mac[6];
    struct nic_stat stat;
};

struct dev_net_state {
    u32 nic_num;
    struct dev_nic_state state[NIC_STATE_MAX_NUM];
};

struct dev_state {
    struct dev_cpu_state cpu_state;
    struct dev_mem_state mem_state;
    struct dev_storage_state storage_state;
    struct dev_net_state net_state;
};

void display_dev_list(void *arg);
void display_dev_state(struct dev_state volatile *dev_state);

#endif